package com.lwd.util;


import org.apache.commons.lang3.StringUtils;

import java.io.*;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.text.DecimalFormat;
import java.text.NumberFormat;
import java.text.ParseException;
import java.util.Date;

/**
 * 一个通用的数据计算类
 * @author guanfu.xie,ouzhouyou@qq.com
 * @time: 2013-6-7 下午09:57:04
 */
public class CommonUtil {

    private static DecimalFormat numberFormat=new DecimalFormat("##.##");

    public static String numberFormat(Number number) throws ParseException {
        if (number == null || number.equals(Double.POSITIVE_INFINITY)||number.equals(Double.NEGATIVE_INFINITY)||number.equals(Double.NaN))
            return "0";
        else
            return numberFormat.format(number);
    }

    /**
     * number/dividend，保留2位小数点,四舍五入
     * @param number 被除数
     * @param dividend 除数
     * @return double
     */
    public static double divide(Number number,int dividend){
        try {
            if(number==null || dividend==0 || number.equals(Double.NaN)){
                return 0.0;
            }
            BigDecimal b1 = new BigDecimal(number.toString());
            BigDecimal b2 = BigDecimal.valueOf(dividend);
            return b1.divide(b2,2,4).doubleValue();
        } catch (Exception e) {
            e.printStackTrace();
        }
        return 0.0;
    }

    /**
     * 格式化数字
     * @param number 需要格式化的数字
     * @return 格式化后的数字 Double
     * @throws ParseException 格式化异常
     */
    public static Double parseDouble(Number number) throws ParseException {
        if (number == null || number.equals(Double.NaN))
            return 0.0;
        else
            return Double.valueOf(numberFormat(number));
    }

    /**
     * 参数为空则返回null，否则调用toString方法返回
     * @param o 任意对象
     * @return 对象toString方法返回值，并去掉两边不可见字符
     */
    public static String toString(Object o) {
        if (o == null)
            return null;
        else
            return StringUtils.trimToNull(o.toString());
    }


    /**
     * 方法描述：解析为int ，如果传入的参数o 为空则返回默认值dft
     *
     * @param: Object o, int dft
     * @return: int
     * @version: 1.0
     * @author: guanfu.xie
     * @version: Dec 2, 2010 2:49:50 PM
     */
    public static Integer parseInt(Object o, int dft) {
        if (o == null)
            return dft;
        if (o.equals(""))
            return dft;
        else
            return Integer.parseInt(o.toString());
    }

    /**
     * 方法描述：解析为double 如果传入的参数o 为空或非数字则返回默认值dft
     *
     * @param: Object o, double dft
     * @return: double
     * @version: 1.0
     * @author: guanfu.xie
     * @version: Dec 17, 2010 8:50:15 PM
     */
    public static Double parseDouble(Object o, double dft) {
        if (o == null) {
            return dft;
        } else {
            return Double.parseDouble(o.toString());
        }
    }

    /**
     * 方法描述：当需要的时间为空时，返回一个默认的时间
     *
     * @param:
     * @return:
     * @version: 1.0
     * @author: guanfu.xie
     * @version: Dec 11, 2010 5:01:20 PM
     */
    public static Date removeNullDate(Date date, Date defaultDate) {
        if (date == null) {
            return defaultDate;
        } else {
            return date;
        }
    }



    /**
     * 方法描述：对num 保留keep位小数
     *
     * @version: 1.0
     * @author: guanfu.xie
     * @version: Mar 19, 2011 9:22:26 PM
     */
    public static Double getRetainDecimal(Double num, int keep) {
        return new BigDecimal(num).setScale(keep, BigDecimal.ROUND_HALF_UP).doubleValue();
    }


    /**
     * 方法描述：Double数据相加
     *
     * @author: guanfu.xie
     */
    public static double sumDouble(Double d1, Double d2) {
        if (null == d1) {
            d1 = 0d;
        }
        if (null == d2) {
            d2 = 0d;
        }
        double dd = new BigDecimal(d1).setScale(2, BigDecimal.ROUND_HALF_DOWN).doubleValue();
        double dd2 = new BigDecimal(d2).setScale(2, BigDecimal.ROUND_HALF_DOWN).doubleValue();
        return new BigDecimal(dd + dd2).setScale(2, BigDecimal.ROUND_HALF_DOWN).doubleValue();
    }

    /**
     * 提供精确的加法运算。
     *
     * @param v1 被加数
     * @param v2 加数
     * @return 两个参数的和
     */
    public static double add(double v1, double v2) {
        BigDecimal b1 = new BigDecimal(Double.toString(v1));
        BigDecimal b2 = new BigDecimal(Double.toString(v2));
        return b1.add(b2).doubleValue();
    }

    /**
     * 计算百分比
     * @param v1
     * @param v2
     * @return
     */
    public static Double percentage(double v1, double v2) {
        // 创建一个数值格式化对象
        BigDecimal bigDecimal1 = new BigDecimal(v1);
        BigDecimal bigDecimal2 = new BigDecimal(v2);

        NumberFormat numberFormat = NumberFormat.getInstance();
        // 设置精确到小数点后2位
        numberFormat.setMaximumFractionDigits(2);
        Double percentage = 0.00;
        if(v2 != 0){
            BigDecimal divide = bigDecimal1.multiply(new BigDecimal(100)).divide(bigDecimal2, 2, RoundingMode.HALF_UP);
            percentage= divide.doubleValue();
        }
        return  percentage;
    }

    /**
     * 方法描述：深度克隆对象
     *
     * @author: gaunfu.xie
     */
    public static Object clone(Object shouldCloneObj) {
        Object obj = null;
        ByteArrayOutputStream bo = null;
        ObjectOutputStream oo = null;
        try {
            //将对象写到流里
            bo = new ByteArrayOutputStream();
            oo = new ObjectOutputStream(bo);
            oo.writeObject(shouldCloneObj);

            //从流里读出
            ByteArrayInputStream bi = new ByteArrayInputStream(bo.toByteArray());
            ObjectInputStream oi = new ObjectInputStream(bi);
            try {
                obj = oi.readObject();
            } catch (ClassNotFoundException e) {
                e.printStackTrace();
            }
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            try {
                if (bo != null) bo.close();
                if (oo != null) oo.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }

        return obj;

    }

    public boolean equals(Object o1, Object o2) {
        if (o1 != null && o2 != null
                && StringUtils.equals(o1.toString(), o2.toString()))
            return true;
        else if (o1 == null && o2 == null)
            return true;
        else
            return true;
    }
}
